<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace cores\authorize\update;

use cores\library\Version;
use cores\exception\BaseException;

/**
 * 一键更新服务
 * Class Update
 */
class Update
{
    // 当前要升级的版本号
    protected string $version;

    // 版本的模块信息
    protected array $modules = [];

    // 更新模块的驱动类
    protected array $updates = [
        'server' => Server::class,
        'database' => Database::class,
    ];

    /**
     * 构造方法
     * @param string $version
     * @param array $modules
     * @throws BaseException
     */
    public function __construct(string $version, array $modules)
    {
        $this->version = $version;
        $this->initModules($modules);
        $this->envTest();
    }

    /**
     * 环境检测
     * @return void
     * @throws BaseException
     */
    private function envTest()
    {
        if (!extension_loaded('zip') || !class_exists('ZipArchive')) {
            throwError('很抱歉，您的php环境不支持Zip，无法使用在线升级');
        }
    }

    /**
     * 初始化更新的模块
     * @param array $modules
     * @return void
     */
    private function initModules(array $modules)
    {
        foreach ($this->updates as $module => $drive) {
            if (isset($modules[$module])) {
                $this->modules[$module] = $modules[$module];
            }
        }
    }

    /**
     * 执行一键更新
     * @return bool
     * @throws BaseException
     */
    public function handle(): bool
    {
        // 设置脚本运行超时时间
        $this->setTimeout();
        // 逐步更新各个模块
        foreach ($this->modules as $module) {
            if (isset($this->updates[$module['key']])) {
                $Update = new $this->updates[$module['key']]($this->version, $module);
                call_user_func([$Update, 'handle']);
            }
        }
        // 更新完成后, 执行数据初始化
        $this->afterInitialize();
        return true;
    }

    /**
     * 数据初始化
     * @throws BaseException
     */
    private function afterInitialize()
    {
        clearstatcache();
        $versionInt = Version::versionToInteger($this->version);
        $Initialize = new Initialize();
        if (method_exists($Initialize, "init_{$versionInt}")) {
            call_user_func([$Initialize, "init_{$versionInt}"]);
        }
    }

    /**
     * 设置脚本运行超时时间
     * @param int $time 超时时间(秒) 0为不限制
     * @return $this
     */
    public function setTimeout(int $time = 0): self
    {
        set_time_limit($time) || ini_set('max_execution_time', $time);
        return $this;
    }
}